//
//  ICSyncManager.m
//  ICome
//
//  Created by zhangrongwu on 16/6/15.
//  Copyright © 2016年 iCom. All rights reserved.
//

#import "ICSyncManager.h"
#import "ICGroup.h"
#import "ICGroupUser.h"
#import "ICMediaManager.h"
#import "ICNotify.h"
#import "ICChnModel.h"

#import "ICGtasksModel.h"
#import "ICGroupListStatus.h"
#import "ICGroupListModel.h"
#import "ICAction.h"
#import "ICMessageModel.h"
#import "iComeApiManager.h"
typedef void(^UpdateGroupInfoHandle)(BOOL END);
@interface ICSyncManager()

@property (nonatomic, strong) NSMutableDictionary *unreadDic;
@property (nonatomic, strong) NSMutableDictionary *timeDic;

@property (nonatomic, copy)ICSyncLoadingStatusBlock syncStatusBlock;
@property (nonatomic, copy)ICSynchronousHandle synchronousHandle;
@property (nonatomic, copy)UpdateGroupInfoHandle updateGroupInfoHandle;
@property (nonatomic, assign)NSInteger reloadIndex;
@property (nonatomic, assign)NSInteger synCount;
@end

@implementation ICSyncManager

+ (instancetype)sharedInstance {
    static dispatch_once_t once;
    static id instance;
    dispatch_once(&once, ^{
        instance = [[ICSyncManager alloc] init];
    });
    return instance;
}

-(instancetype)init {
    if (self = [super init]) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(messageDidReceived:) name:NotificationReceiveMessage object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateGroupListNotific:) name:NotificationUpdateGroupList object:nil];
    }
    return self;
}

#pragma mark - message receive

- (void)messageDidReceived:(NSNotification *)notifi
{
    NSDictionary *dic = notifi.object;   // 消息体
    NSDictionary *userinfo = notifi.userInfo; // command
    NSString *command = [NSString stringWithFormat:@"%@",[userinfo objectForKey:@"command"]];
    
    NSString *gId = [dic objectForKey:@"to"];
    // command 是11处理message对象，command是12处理action对象
    if ([command isEqualToString:@"12"]) { // 处理cmdList
        NSArray *list   = [NSArray arrayWithObject:dic];
        [[ICSyncManager sharedInstance] updateApplicationCommandList:list];
        return;
    }
    NSString *type = [NSString stringWithFormat:@"%@",[dic objectForKey:@"type"]];
    if ([type isEqualToString:@"9"]) { // 送达号  ***** 暂时不做处理
    }
    
    if ([type isEqualToString:@"0"]) { // 系统消息(有人建群的通知) ***** 需更新对应组信息
        [[ICSyncManager sharedInstance] updateGroupListFinish:nil failure:nil];
    }
    
    // 判断当前群组是否存在 不存在则进行拉去群组操作
    if (![ICMessageDatabase isGroupExisted:gId]) {
        [[ICSyncManager sharedInstance] updateGroupListFinish:nil failure:nil];
        return;
    }
    // 消息到来时的声音
    [ICTools playMsgSoundWithStatus:[[dic objectForKey:@"status"] integerValue]]; // 需权限控制
    // 收到消息则表示该群有效，则把valid置为1
    [ICMessageDatabase invalidGroup:gId valid:YES];
    // 更新对应组的本地显示状态
    [ICMessageDatabase changeGroupLocalType:YES GroupId:gId];
    // 针对客服 本地组 做特殊处理
    [ICMessageHelper setServeGroupActive:gId];
    
    WEAKSELF;
    [ICMessageHelper messageTypeWithMessage:dic finished:^(ICMessageFrame *messageF) {
        if ([messageF.model.message.to isEqualToString:[NSString stringWithFormat:@"tdo_%@", [ICUser currentUser].eId]]) { // 待办组 status 置为 ICMessageStatus_unRead
            messageF.model.message.status = ICMessageStatus_unRead;
        }
        if ([messageF.model.message.type isEqualToString:TypeVoice]) {
            messageF.model.message.status = ICMessageStatus_unRead;
        }
        [ICMessageDatabase saveMessage:messageF.model]; // 统一存储消息
        [weakSelf unReadCountPlus:gId];
        [ICMessageHelper changeGroupStatus:dic];
        [weakSelf reloadDataSource];
        [[NSNotificationCenter defaultCenter] postNotificationName:NotificationReceiveMessageUpdate object:@{@"ICMessageFrame":messageF}];
    }];
}

// 网络断开重连等调用该通知
- (void)updateGroupListNotific:(NSNotification *)notification
{
    self.synCount++;
    if (!self.isSynchronizing) {
        [self syncManager];
    }
}

- (void)syncManager {
    self.isSynchronizing = YES;
    self.synCount = 0;
    // 由于tcp内部线程问题、dispatch_barrier_async并没有达到预期效果:导致无法等待GroupList与DirectList执行完成后去执行CmdList
    dispatch_queue_t concurrentQueue = dispatch_queue_create("currentSync.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^(){
        [[ICSyncManager sharedInstance] updateGroupListFinish:^(id object) {
        } failure:^(id object) {
        }];
    });
    dispatch_async(concurrentQueue, ^(){
        [[ICSyncManager sharedInstance] updateCmdListFinish:nil failure:nil];
    });
    dispatch_barrier_async(concurrentQueue, ^(){
        [[NSNotificationCenter defaultCenter] postNotificationName:NotificationEnterForegroundChatRefresh object:nil];
    });
}

#pragma mark - groupList
- (void)updateGroupListFinish:(SyncSuccess)success
                      failure:(SyncFailure)failure {
    self.unreadDic = nil;
    self.timeDic = nil;
    self.reloadIndex = 0;
    NSNumber *groupLastUpdate = [ICMessageHelper getLastUpdate];
    
    NSDictionary *param = @{@"eId":[ICUser currentUser].eId == nil ? @"" : [ICUser currentUser].eId,@"lastUpdate":groupLastUpdate};
    
    [[ICSocketRequestManager sharedInstance] updateGroupListWithObject:param Success:^(id object) {
        
        ICGroupListStatus *status = [ICGroupListStatus mj_objectWithKeyValues:[object objectForKey:@"data"]];
        NSMutableArray *pullList = [[NSMutableArray alloc] init];
        __block NSInteger groupInfoUpdateCount = 0;
        dispatch_async(YYDispatchQueueGetForQOS(NSQualityOfServiceBackground), ^{
            for (NSInteger index = 0 ; index <= status.groupList.count; index++) {
                ICGroupListModel *model = [status.groupList objectAtIndex:index];
                if(model.msg) {
                    [self.timeDic setObject:[model.msg objectForKey:@"st"] forKey:[model.msg objectForKey:@"to"]];
                    if (![ICMessageDatabase isGroupExisted:[model.msg objectForKey:@"to"]]) {
                        [self.unreadDic setObject:@(model.unread) forKey:model.gId];//DISPATCH_QUEUE_PRIORITY_DEFAULT
                        [self updateGroupInfo:model.gId UpdateGroupInfoHandle:^(BOOL END) {
                            groupInfoUpdateCount++;
                            if (groupInfoUpdateCount == index) {[self reloadDataSource];}
                        }];
                    } else {
                        [ICMessageDatabase updateGroupUnreadMessageCountWithGroupId:model.gId count:model.unread];
                        groupInfoUpdateCount++;
                        if (groupInfoUpdateCount == index) {[self reloadDataSource];}
                    }
                    // 最后一条消息是否需要保存(同步数据消息id与本地最新id是否相同)
                    if (![ICMessageDatabase isMessageExisted:model.gId messageId:[[model.msg objectForKey:@"id"] stringValue]]) {
                        [ICMessageDatabase changeGroupLocalType:YES GroupId:model.gId];// 改变本地组的显示状态
                        NSDictionary *dict = [self pullMessage:model.msg];
                        if (![ICTools isObjEmpty:dict]) {
                            [pullList addObject:dict];
                        }
                        [ICMessageHelper setServeGroupActive:model.gId];
                    }
                }
            }
            if (pullList.count > 0) {
                [self mPullMessageFromGroupsInfo:pullList LastUpdate:status.lastUpdate];
            } else {
                self.syncLoadingStatus = ICSyncLoadingStatusFinish; // 简单的处理 同步CmdList
                [ICMessageHelper setLastUpdate:[status.lastUpdate numberValue]];
            }
            [self reloadDataSource];
        });
        
    } Failure:^(NSError *error, id other) {
        NSLog(@"updateGroupList error :%@",error);
    }];
}

- (void)updateGroupInfo:(NSString *)gId UpdateGroupInfoHandle:(UpdateGroupInfoHandle)Handle {
    NSDictionary *param = @{@"gId":gId,
                            @"eId":[ICUser currentUser].eId,
                            @"lastUpdate":[ICMessageHelper getGroupInfoLastUpdate:gId]};
    [[ICSocketRequestManager sharedInstance] updateGroupInfoWithObject:param Success:^(id object) {
        
        NSDictionary *data = [object objectForKey:@"data"];
        NSDictionary *gInfo = [data objectForKey:@"gInfo"];
        ICGroup *group = [ICGroup mj_objectWithKeyValues:gInfo];
        if ([[gInfo objectForKey:@"master"] isEqualToString:[ICUser currentUser].eId]) {
            group.master = 1;
        } else {
            group.master = 0;
        }
        
        group.lastMsgTime = [[self.timeDic objectForKey:group.gId] integerValue];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
            [ICMessageDatabase saveGroup:group];
            [ICMessageDatabase updateGroupUnreadMessageCountWithGroupId:group.gId count:[[self.unreadDic objectForKey:group.gId] intValue]];
            
            NSArray *arrs = [data objectForKey:@"gUsers"];
            NSMutableArray *saveUsers = [[NSMutableArray alloc] init];
            NSMutableArray *groupUsers = [[NSMutableArray alloc] init];
            for (NSDictionary *dict in arrs) {
                ICGroupUser *groupUser = [[ICGroupUser alloc] init];
                ICUser *gUser = [ICUser mj_objectWithKeyValues:dict];
                if (gUser.valid == 0) {
                    [ICMessageDatabase deleteGroupUserWithGroupId:group.gId eId:gUser.eId];
                    
                } else {
                    groupUser.eId = gUser.eId;
                    groupUser.valid = gUser.valid;
                    groupUser.nName = gUser.nName == nil ? gUser.eName : gUser.nName;
                    if (groupUser.valid == 1) {
//                        [ICMessageDatabase saveUser:gUser];
                        [saveUsers addObject:gUser];
                    }
                    [groupUsers addObject:groupUser];
//                    [ICMessageDatabase saveGroupUserWithGroupId:group.gId groupUser:groupUser];
                }
            }
            [ICMessageDatabase saveUsers:saveUsers];
            [ICMessageDatabase saveGroupUsersWithGroupId:group.gId groupUsers:groupUsers];
            if (Handle) {
                Handle(YES);
            }
        });
     
        [ICMessageHelper setGroupInfoLastUpdate:[data objectForKey:@"lastUpdate"] gId:group.gId];
    } Failure:^(NSError *error, id other) {
        if (Handle) {
            Handle(NO);
        }
    }];
}

// 最后一条消息的处理
- (NSDictionary *)pullMessage:(NSDictionary *)msgDic {
    NSString *gId               = [NSString stringWithFormat:@"%@",[msgDic objectForKey:@"to"]];
    NSInteger receivedLastMsgId = [[msgDic objectForKey:@"id"] integerValue];
    NSInteger localMaxMsgId     = [ICMessageDatabase maxMessageId:gId];
    NSString *localIndex        = [NSString stringWithFormat:@"%ld",(long)localMaxMsgId];
    //    WEAKSELF
    NSInteger discrepancy = receivedLastMsgId-localMaxMsgId;
    if (receivedLastMsgId == 1) { // 新创建的组的第一条直接存
        [ICMessageHelper messageTypeWithMessage:msgDic finished:^(ICMessageFrame *messageF) {
            [ICMessageDatabase saveMessage:messageF.model];
            NSDictionary *userInfo = @{@"gId":messageF.model.message.to};
            [[NSNotificationCenter defaultCenter] postNotificationName:NotificationFirstMessage object:nil userInfo:userInfo]; // 去更新一下
            //            [weakSelf reloadDataSource];
        }];
        return nil;
    }
    if (discrepancy == 1) {
        [ICMessageHelper messageTypeWithMessage:msgDic finished:^(ICMessageFrame *messageF) {
            [ICMessageDatabase saveMessage:messageF.model];
            [[NSNotificationCenter defaultCenter] postNotificationName:NotificationPushDidReceived object:nil];
            //            [weakSelf reloadDataSource];
        }];
        return nil;
    } else if (discrepancy <= 20 && discrepancy > 1) {
        NSDictionary *param = @{@"gId":gId,
                                @"localIndex":localIndex};
        return param;
    }
    else if (discrepancy > 20) {
        // 保存最后一条消息，进去后可以repull
        //        [ICMessageDatabase clearChatRecord:gId];
        [ICMessageHelper messageTypeWithMessage:msgDic finished:^(ICMessageFrame *messageF) {
            [ICMessageDatabase saveMessage:messageF.model];
            //            [weakSelf reloadDataSource];
        }];
        return nil;
    }
    return nil;
}

- (void)mPullMessageFromGroupsInfo:(NSMutableArray *)groupsInfo LastUpdate:(NSString *)lastUpdate {
    [[ICSocketRequestManager sharedInstance] mPullMessageWithObject:groupsInfo Success:^(id object) {
        NSArray *data = [object objectForKey:@"data"];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
            for (NSDictionary *message in data) {
                if (![ICTools isObjEmpty:message]) {
                    [ICMessageHelper changeGroupStatus:message];
                    [ICMessageHelper messageTypeWithMessage:message finished:^(ICMessageFrame *messageF) {
                        [ICMessageDatabase saveMessage:messageF.model];
                    }];
                }
            }
            [self reloadDataSource];
            self.syncLoadingStatus = ICSyncLoadingStatusFinish; // 简单的处理 同步CmdList
            self.syncProgress = 1.0f;
        });
        [ICMessageHelper setLastUpdate:[lastUpdate numberValue]];
        
    } Failure:^(NSError *error, id other) {
        self.syncLoadingStatus = ICSyncLoadingStatusFinish; // 简单的处理 同步CmdList
    }];
}

#pragma mark - cmdList
/**
 grouplist/directlist更新结束后更新CmdList
 */
- (void)updateCmdListFinish:(SyncSuccess)success
                    failure:(SyncFailure)failure {
    NSDictionary *param = @{@"eId":[ICUser currentUser].eId == nil ? @"" : [ICUser currentUser].eId};
    [[ICSocketRequestManager sharedInstance] updateCmdListWithObject:param Success:^(id object) {
        NSLog(@"updateCmdListWithObject %@", object);
        NSArray *dictList = [[object objectForKey:@"data"] objectForKey:@"cmdList"];
        [self updateApplicationCommandList:dictList];
    } Failure:^(NSError *error, id other) {
        NSLog(@"request cmdList error %@", error);
    }];
}


- (void)updateApplicationCommandList:(NSArray *)CommandList {
    NSArray *tempList =  [CommandList sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1[@"id"] compare:obj2[@"id"] options:NSNumericSearch] == NSOrderedDescending;
    }];
    for (NSDictionary *dict in tempList) {
        ICAction *action = [ICAction mj_objectWithKeyValues:dict];
        [self confirmAction:action]; // 回复确认
        switch (action.type) {
            case ICActionType_READ:
            {
                [ICMessageDatabase messageDidRead:action.gId msgId:action.msgId];
                break;
            }
            case ICActionType_BACK:
            {
                NSInteger currentDate = [ICMessageHelper currentMessageTime];
                [ICMessageDatabase messageBackAction:action.gId messageId:action.msgId lastMsgTime:currentDate];
                NSDictionary *userInfo = @{
                                           @"gId":action.gId,
                                           @"msgId":action.msgId
                                           };
                [[NSNotificationCenter defaultCenter] postNotificationName:NotificationBackMsgNotification object:nil userInfo:userInfo];
                [self reloadDataSource];
                break;
            }
            case ICActionType_UPTO:
            {
                [ICMessageDatabase updateGroupUnreadMessageCountWithGroupId:action.gId count:action.status];
                [self reloadDataSource];
                break;
            }
            case ICActionType_KICK:
            {
                [ICMessageDatabase kickUserAction:action.gId messageTxt:action.msgId];
                // 插入一条你被请出会话的消息
                ICMessageFrame *messageF = [ICMessageHelper createMessageFrame:TypeSystem
                                                                       content:action.msgId
                                                                          path:nil
                                                                          from:nil
                                                                            to:action.gId
                                                                           lnk:nil
                                                                       fileKey:nil
                                                                      isSender:NO
                                                      receivedSenderByYourself:NO];
                messageF.model.message.messageId = [NSString stringWithFormat:@"%d",action.status];
                [ICMessageDatabase saveMessage:messageF.model];
                [self unReadCountPlus:action.gId];
                [self reloadDataSource];
                [[NSNotificationCenter defaultCenter] postNotificationName:NotificationKickUserNotification object:@{@"ICMessageFrame":messageF}];
                break;
            }
            case ICActionType_OPOK:
            {
                [ICMessageDatabase setGtasksMsgId:action.msgId Status:[NSString stringWithFormat:@"%d", action.status]];
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:NotificationUpdateGtasksList object:nil];
                });
                break;
            }
            case ICActionType_BDRT:
            {
                [ICMessageDatabase deleteDeliverMessage:action.gId msgId:action.msgId];
                break;
            }
            case ICActionType_GUPD:
            {
                NSDictionary *msgId = [NSDictionary dictionaryWithJsonString:action.msgId];
                NSString *gName = [msgId objectForKey:@"gName"];
                NSString *gId   = [msgId objectForKey:@"gId"];
                NSString *photoId = [msgId objectForKey:@"photoId"];
                [ICMessageDatabase updateGroupSyn:gId gName:gName photoId:photoId];
                [self reloadDataSource];
                break;
            }
            case ICActionType_UUPD:
            {
                // 目前只有头像能改
                NSDictionary *msgId = [NSDictionary dictionaryWithJsonString:action.msgId];
                NSString *photoId = [msgId objectForKey:@"photoId"];
                NSString *eId     = [msgId objectForKey:@"eId"];
                [ICMessageDatabase updateUserPhotoId:photoId eId:eId];
                [self reloadDataSource];
                // 更新用户表数据
                if ([eId isEqualToString:[ICUser currentUser].eId]) {
                    [ICUser currentUser].photoId = photoId;
                    [ICUser updateUserInfo];
                }
                break;
            }
            case ICActionType_DUPD:
            {
                NSDictionary *msgId = [NSDictionary dictionaryWithJsonString:action.msgId];
                NSString *photoId = [msgId objectForKey:@"photoId"];
                NSString *dId     = [msgId objectForKey:@"dId"];
                NSString *dName   = [msgId objectForKey:@"dName"];
                NSInteger valid   = [[msgId objectForKey:@"valid"] integerValue];
                [ICMessageDatabase updateDeliverInfo:photoId dId:dId dName:dName valid:valid];
                break;
            }
            case ICActionType_OFFL:
            {
                [MBProgressHUD showError:@"账号异常，请重新登录"];
                [ICTools outLogIn];
                break;
            }
            case ICActionType_STOP:
            {
                [MBProgressHUD showError:@"账号异常，请重新登录"];
                [ICTools initICom];
                break;
            }
            case ICActionType_UUPN:
            {
                NSDictionary *msgId = [NSDictionary dictionaryWithJsonString:action.msgId];
                NSString *gId = [msgId objectForKey:@"gId"];
                NSString *eId = [msgId objectForKey:@"eId"];
                NSString *nName = [msgId objectForKey:@"nName"];
                [ICMessageDatabase updateNickNameWith:eId gId:gId nName:nName];
                break;
            }
            case ICActionType_TRSF:
            {
                [ICMessageDatabase deleteGroupWithGroupId:action.gId];
                break;
            }
            case ICActionType_DELE: // 禁用客服组
            {
                [ICMessageDatabase changeGroupLocalType:NO GroupId:[NSString stringWithFormat:@"svr_%@", [ICUser currentUser].eId]];
                ALERT(@"您好，您已不再是平台客服人员！");
                [[NSNotificationCenter defaultCenter] postNotificationName:@"SERVEDELEACTION" object:nil];
                break;
            }
            case ICActionType_UPHD:
            {
                
               
                break;
            }
            case ICActionType_UPSCH:
            {
                NSLog(@"日程消息同步");
               
                break;
            }
            case ICActionType_TOPMSG:
            {
                NSString *key = [NSString stringWithFormat:@"TOPMSG_%@_%@",[ICUser currentUser].eId,action.gId];
                [[NSUserDefaults standardUserDefaults] setObject:dict[@"msgId"] forKey:key];
                [[NSNotificationCenter defaultCenter] postNotificationName:NotificationGroupTopMessage object:nil];
                break;
            }
                
            case ICActionType_TEST:
            {
                NSLog(@"测试action");
                break;
            }
            default:
                break;
        }
    }
}

/**
 action 回复确认
 */
- (void)confirmAction:(ICAction *)action {
    // id 为空时 返回
    if (![ICTools stringEmpty:action.ID]) {
        NSDictionary *param = @{@"id" : action.ID,
                                @"type" : [NSNumber numberWithInt:action.type],
                                @"gId": action.gId,
                                @"msgId" : action.msgId == nil ? @"" : action.msgId,
                                @"time" : [NSNumber numberWithLong:action.time],
                                @"status" : [NSNumber numberWithInt:action.status]};
        [[ICSocketRequestManager sharedInstance] confirmActionWithObject:param];
    }
}

/**
 未读数加1
 */
- (void)unReadCountPlus:(NSString *)gId
{
    int unreadCount = [ICMessageDatabase getGroupUnreadMessageCountWithGroupId:gId];
    [ICMessageDatabase updateGroupUnreadMessageCountWithGroupId:gId count:(unreadCount+1)];
}

#pragma mark - comm
/**
 通知各界面处理数据
 */
- (void)reloadDataSource {
    [[NSNotificationCenter defaultCenter] postNotificationName:NotificationReloadDataIMSource object:nil];
    NSLog(@"reloadIndexreloadIndexreloadIndex : %ld", self.reloadIndex++);
    [[iComeApiManager instance] updateUnreadMsg];
}

/**
 设置连接状态与数据同步进度
 */
- (void)setSyncLoadingStatusChangeBlock:(ICSyncLoadingStatusBlock)block
                            Synchronous:(ICSynchronousHandle)handle {
    self.syncStatusBlock = block;
    self.synchronousHandle = handle;
}

/**
 连接状态回调
 */
-(void)setSyncLoadingStatus:(ICSyncLoadingStatus)syncLoadingStatus {
    if (syncLoadingStatus == ICSyncLoadingStatusFinish) {
        self.isSynchronizing = NO; // 可重新开始syn
        if (self.synCount > 0) {
            [self syncManager];
        }
    }
    if (self.syncStatusBlock) {
        self.syncStatusBlock(syncLoadingStatus);
    }
}

/**
 设置同步数据的进度
 */
-(void)setSyncProgress:(CGFloat)syncProgress {
    if (self.synchronousHandle) {
        self.synchronousHandle(syncProgress);
    }
}

/**
 同步成功后 继续分享
 */
- (void)dispatch_after_shareInfo {
    NSDictionary *info = [[NSUserDefaults standardUserDefaults] objectForKey:@"dispatch_shareInfo"];
    if (![ICTools isObjEmpty:info]) {
       // 分享成功后
    }
}

#pragma mark - setter and getter

- (NSMutableDictionary *)unreadDic
{
    if (!_unreadDic) {
        _unreadDic = [NSMutableDictionary dictionary];
    }
    return _unreadDic;
}

- (NSMutableDictionary *)timeDic
{
    if (!_timeDic) {
        _timeDic = [NSMutableDictionary dictionary];
    }
    return _timeDic;
}
-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


@end
